//
// Created by 朱宗辉 on 25-6-8.
//

#ifndef FAT32_H
#define FAT32_H
#include <fuquOS/type.h>

typedef struct {
    u8  jumpBoot[3];             // 跳转指令
    u8  OEMName[8];              // OEM 名称
    u16 bytesPerSector;          // 每扇区字节数
    u8  sectorsPerCluster;       // 每簇扇区数
    u16 reservedSectorCount;     // 保留扇区数
    u8  numFATs;                 // FAT 表数
    u16 rootEntryCount;          // 根目录最大条目数（FAT32为0）
    u16 totalSectors16;          // 总扇区数（小于65535时使用）
    u8  media;                   // 介质类型
    u16 fatSize16;               // FAT大小（FAT12/16用）
    u16 sectorsPerTrack;
    u16 numHeads;
    u32 hiddenSectors;
    u32 totalSectors32;          // 总扇区数
    u32 fatSize32;               // 每个 FAT 表所占扇区数
    u16 extFlags;
    u16 fsVersion;
    u32 rootCluster;             // 根目录起始簇号
    u16 fsInfo;
    u16 backupBootSector;
    u8  reserved[12];
    u8  driveNumber;
    u8  reserved1;
    u8  bootSignature;
    u32 volumeID;
    u8  volumeLabel[11];
    u8  fsType[8];
    u8  bootCode[420];
    u16 signature;
} __attribute__((packed)) BPB_FAT32;

// 目录项
typedef struct {
    u8  name[11];         // 【11 字节】文件名 + 扩展名（8+3）
    // - 不带点，例如："KERNEL  BIN"
    // - 前 8 字节是主文件名，后 3 字节是扩展名
    // - 空格填充，不足补空格
    // - 删除文件的首字节为 0xE5
    // - 0x00 表示目录项结束（之后全空）

    u8  attr;             // 【1 字节】文件属性
    // 位标志字段，可组合使用（用位掩码操作）
    // 0x01: 只读 (Read Only)
    // 0x02: 隐藏 (Hidden)
    // 0x04: 系统 (System)
    // 0x08: 卷标 (Volume Label)
    // 0x10: 目录 (Subdirectory)
    // 0x20: 普通文件 (Archive)
    // 举例: 0x10 表示目录，0x20 表示普通文件

    u8  nt_reserved;      // 【1 字节】保留字段
    // Windows 用于大小写标记（一般为 0）

    u8  create_time_tenths; // 【1 字节】创建时间的百分之一秒（0~199）
    // 真实精度并不高，实际常为 0

    u16 create_time;      // 【2 字节】创建时间（低位）
    // 格式为 FAT 时间：
    // bits 15–11: 小时 (0–23)
    // bits 10–5 : 分钟 (0–59)
    // bits 4–0  : 秒数 / 2 (0–29)

    u16 create_date;      // 【2 字节】创建日期
    // bits 15–9 : 年份 - 1980 (0–127, 即1980–2107)
    // bits 8–5  : 月份 (1–12)
    // bits 4–0  : 日 (1–31)

    u16 access_date;      // 【2 字节】最后访问日期（不包含时间）

    u16 cluster_high;     // 【2 字节】起始簇号高 16 位
    // FAT32 的簇号是 32 位，但存放在两个地方：
    // cluster = (cluster_high << 16) | cluster_low

    u16 modify_time;      // 【2 字节】最后修改时间（与 create_time 格式相同）

    u16 modify_date;      // 【2 字节】最后修改日期（与 create_date 格式相同）

    u16 cluster_low;      // 【2 字节】起始簇号低 16 位

    u32 file_size;        // 【4 字节】文件大小（字节）
    // - 目录项为目录时，该字段为 0
} __attribute__((packed)) DirEntry;



void fat32_init();

// 将簇号转换为 LBA
u32 cluster_to_lba(u32 cluster, BPB_FAT32 *bpb, u32 partition_start_lba);

#endif //FAT32_H
